﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;
using System.Reflection;
using System.Collections;
using System.Configuration;
using com.clinica.config;
using com.clinica.business.entities;
/****************************************************************************************
 * Sistema    : Sistema de Gestión de Clinica
 * Modulo     : Facturación y Presupuestos
 * Descripción: 
 * Autor      : JPEREZ
 * Fecha      : 2011-06-01
 ****************************************************************************************/

namespace com.clinica.dao.sql
{
    public static class ElManager
    {
        public static List<T> EjecutarStore<T>(Comando comamd, DataBase bd)
        {
            #region Definiendo Variables, abriendo la Conexion
            List<T> entidades = new List<T>();
            SqlDataReader myDataReader;
            SqlConnection cn = new SqlConnection ();
            switch (bd)
            {
                case DataBase.CLINICA_WEB:
                    cn = new SqlConnection(ConfigurationManager.ConnectionStrings[new BeginConfig().Context + "CLINICA"].ConnectionString);
                    break;
                case DataBase.SEGURIDAD_CLINICA:
                    cn = new SqlConnection(ConfigurationManager.ConnectionStrings[new BeginConfig().Context + "SEGURIDAD"].ConnectionString);
                    break;
                default:
                    break;
            }            
            cn.Open();
            #endregion
            #region Definiendo el Command, Pasando parametros Y ejecutando el procedeure
            SqlCommand myCommand = new SqlCommand(comamd.CommandName, cn);
            myCommand.CommandType = CommandType.StoredProcedure;
            foreach (Parameter parm in comamd.ListaParametro)
            {
                myCommand.Parameters.Add(parm.Name, obtenerTipoDatoBD(parm)).Value = parm.Value;
            }
            myDataReader = myCommand.ExecuteReader();
            #endregion
            #region Se aplica refletion
            PropertyInfo[] propiedades = typeof(T).GetProperties();
            try
            {
                ArrayList columnasConsultadas = new ArrayList();
                for (int i = 0; i < myDataReader.FieldCount; i++) { columnasConsultadas.Add(myDataReader.GetName(i)); }
                while (myDataReader.Read())
                {
                    T entidad = Activator.CreateInstance<T>();
                    foreach (PropertyInfo propiedad in propiedades)
                    {
                        Attribute item = Attribute.GetCustomAttribute(propiedad, typeof(Column));
                        if (item is Column)
                        {
                            try
                            {
                                Column column = (Column)item;
                                if (columnasConsultadas.IndexOf(column.Name) > -1)
                                {
                                    propiedad.SetValue(entidad, myDataReader.GetValue(myDataReader.GetOrdinal(column.Name)), null);
                                }
                            }
                            catch (Exception) { }
                        }
                    }
                    entidades.Add(entidad);
                }
            }
            finally
            {
                myDataReader.Close();
                cn.Close();
            }
            #endregion
            return entidades;
        }

        private static DbType obtenerTipoDatoBD(Parameter parametro)
        {
            if (parametro.Value == null)
                throw new NullReferenceException();
            #region Determinar que tipo de Dato para el SQL es
            Type tipo = parametro.Value.GetType();
            if (tipo.Equals(System.Type.GetType("System.String")))
                return DbType.String;
            else if (tipo.Equals(System.Type.GetType("System.Int32")))
                return DbType.Int32;
            else if (tipo.Equals(System.Type.GetType("System.DateTime")))
                return DbType.DateTime;
            else if (tipo.Equals(System.Type.GetType("System.Byte[]")))
                return DbType.Binary;
            else if (tipo.Equals(System.Type.GetType("System.Double")))
                return DbType.Decimal;
            #endregion
            return DbType.String;

        }

    }
}
